#include<iostream>
#include<memory>//智能指针的头文件
#include<sys/epoll.h>
#include<unistd.h>
#include"Socket.hpp"
#include"Log.hpp"

using namespace SocketModule;
using namespace LogModule;
class PollSever
{
    const static int size = 4096;
    const static int defaultfd = -1;
public:
    PollSever(uint16_t port):_listensock(std::make_unique<TcpSocket>()), _isruning(false)
    {
        _listensock->BuildTcpServerSocketMethod(port);//一键构建套接字


        //创建一个epoll模型
        _epfd = epoll_create(256);//函数的参数是几都无所谓,现在已经弃用了
        if(_epfd < 0)
        {
            LOG(LogLevel::FATAL) << "epoll_create erro";
            exit(EPOLL_CREATE);
        }


        //将监听的文件描述符放入添加到epoll底层的红黑树中
        epoll_event event;
        event.events = EPOLLIN;//关心读事件
        // 你把任何想随 fd 一起带回的小数据（fd 本身、指针、甚至自研索引）扔进去，当事件就绪时就能 
        // 零额外查找 地取回，从而把 epoll_wait 的 O(1) 优势延伸到业务层
        event.data.fd = _listensock->Fd();//用户的数据内核不会修改
        int n = epoll_ctl(_epfd, EPOLL_CTL_ADD, _listensock->Fd(), &event);
        if(n < 0)
        {
            LOG(LogLevel::FATAL) << "epoll_ctl erro";
            exit(EPOLL_CTL);
        }
        
    }
    void Start()
    {
        _isruning = true;
        while(_isruning)
        {
            int timeout = 10000;
            int n = epoll_wait(_epfd, _events, size, timeout);
            switch(n)
            {
                case -1:
                    LOG(LogLevel::FATAL) << "add epoll_wait error";
                    break;
                case 0:
                    LOG(LogLevel::FATAL) << "timeout...";
                    break;
                default:
                    Dispatcher(n);

            }
        }
        _isruning = false;
    }
    //事件派发器
    void Dispatcher(int epnum)
    {
        for(int i = 0; i < epnum; i++)
        {
            if(_events[i].events & EPOLLIN)
            {
                //有读事件就绪
                if(_events[i].data.fd == _listensock->Fd())
                {
                    //连接到来
                    Accepter();
                }
                else
                {
                    //普通事件到来
                    Recver(i);
                }
            }
        }
    }
    //链接管理器
    void Accepter()
    {
        Inet_Addr client;//获得用户数据

        int socket = _listensock->Accept(&client);
        if(socket > 0)
        {
            //监听成功
            epoll_event event;
            event.events = EPOLLIN;//关心读事件
            event.data.fd = socket;//用户的数据内核不会修改
            int n = epoll_ctl(_epfd, EPOLL_CTL_ADD, socket, &event);
            if(n < 0)
            {
                LOG(LogLevel::FATAL) << "add epoll_ctl erro";
            }
            else
            {
                LOG(LogLevel::FATAL) << "epoll_ctl success" << socket;
            }

        }
    }

    //I/O处理器
    void Recver(int pos)
    {
        char buffer[1024];
        int n = recv(_events[pos].data.fd, buffer, sizeof buffer - 1, 0);
        if(n > 0)
        {
            //读取成功
            buffer[n - 1] = 0;
            std::cout << buffer << std::endl;
        }
        else if(n == 0)
        {
            //对端客户端关闭
            LOG(LogLevel::DEBUG) << "client out...";
            int m = epoll_ctl(_epfd, EPOLL_CTL_DEL, _events[pos].data.fd, nullptr);
            if(m > 0)
            {
                LOG(LogLevel::INFO) << "epoll_ctl remove sockfd success: " << _events[pos].data.fd;
            }
            close(_events[pos].data.fd);

        }
        else 
        {
            //读取失败
            LOG(LogLevel::DEBUG) << "recv error";
            int m = epoll_ctl(_epfd, EPOLL_CTL_DEL, _events[pos].data.fd, nullptr);
            if(m > 0)
            {
                LOG(LogLevel::INFO) << "epoll_ctl remove sockfd success: " << _events[pos].data.fd;
            }
            close(_events[pos].data.fd);
        }
    }
    // void PrintFd()
    // {
    //     //打印监视的文件描述符
    //     std::cout << "_fds[]: ";
    //     for(int i = 0; i < size; i++)
    //     {
    //         if(_fds[i].fd == defaultfd)
    //         {
    //             continue;
    //         }
    //         std::cout << _fds[i].fd << " ";
    //     }
    //     std::cout << std::endl;
    // }
    //暂停服务器
    void Stop()
    {
        _isruning = false;
    }
    ~PollSever()
    {
        ;
    }
private:
    std::unique_ptr<Socket> _listensock;//TCP基类监听端口的文件描述符
    bool _isruning;//服务的运行状态

    int _epfd;

    struct epoll_event _events[size];//设置能监事描述符的大小
};